package com.tiger.web;

import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.propertyeditors.PropertiesEditor;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;

import com.tiger.lbs.Coordinate;
import com.tiger.utils.LangUtils;

public class BaseApi {
	
	protected ThreadLocal<HttpServletResponse> responseHolder = new ThreadLocal<HttpServletResponse>();
	protected ThreadLocal<HttpServletRequest> requestHolder = new ThreadLocal<HttpServletRequest>();
	
	@ModelAttribute
	protected void setResponse(HttpServletResponse response) {
		this.responseHolder.set(response);
	}

	@ModelAttribute
	protected void setRequest(HttpServletRequest request) {
		this.requestHolder.set(request);
	}

	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		// RequestParam反序列化
		binder.registerCustomEditor(LocalDate.class, new LocalDateEditor());
		binder.registerCustomEditor(LocalTime.class, new LocalTimeEditor());
		binder.registerCustomEditor(LocalDateTime.class, new LocalDateTimeEditor());
	}
	
	
	private Object createMsg(int code, String msg) {
		Map<String, Object> o = new HashMap<>();
		o.put("msg", msg);
		o.put("code", code);
		return o;
	}

	protected Object notFound(String reason, Object... arguments) {
		reason = LangUtils.get(reason);
		responseHolder.get().setStatus(SC_NOT_FOUND);
		return createMsg(SC_NOT_FOUND, reason);
	}
	
	protected Object unAuthorized() {
		responseHolder.get().setStatus(SC_UNAUTHORIZED);
		return createMsg(SC_UNAUTHORIZED, "");
	}
	

	protected Object forbidden(String reason, Object... arguments) {
		reason = LangUtils.get(reason);
		responseHolder.get().setStatus(SC_FORBIDDEN);
		return createMsg(SC_FORBIDDEN, reason);
	}
	
	protected Object badRequest(String reason, Object... arguments) {
		reason = LangUtils.get(reason);
		responseHolder.get().setStatus(SC_BAD_REQUEST);
		return createMsg(SC_BAD_REQUEST, reason);
	}
	
	protected Object badRequest(BindingResult result) {
		String reason = result.getAllErrors().iterator().next().getDefaultMessage();
		return badRequest(reason);
	}
	
	protected Object fail(String reason, Object... arguments) {
		reason = LangUtils.get(reason);
		responseHolder.get().setStatus(SC_INTERNAL_SERVER_ERROR);
		return createMsg(SC_INTERNAL_SERVER_ERROR, reason);
	}
	
	protected Object succ() {
		return succ(null);
	}
	
	protected Object succ(Object result) {
		Map<String, Object> o = new HashMap<>();
		o.put("msg", "succ");
		o.put("code", SC_OK);
		if(result != null) {
			o.put("result", result);
		}
		return o;
	}
	
	protected Object hasExisted(String reason) {
		return createMsg(420, reason);
	}
	
	protected Object outOfDate(String reason) {
		return createMsg(421, reason);
	}
	
	public class LocalDateTimeEditor extends PropertiesEditor {
	    @Override
	    public void setAsText(String text) throws IllegalArgumentException {
	        if (!StringUtils.isEmpty(text)) {
	            setValue(LocalDateTime.parse(text));
	        }
	    }
	}
	
	public class LocalDateEditor extends PropertiesEditor {
	    @Override
	    public void setAsText(String text) throws IllegalArgumentException {
	        if (!StringUtils.isEmpty(text)) {
	            setValue(LocalDate.parse(text));
	        }
	    }
	}
	
	public class CoordinateEditor extends PropertiesEditor {
	    @Override
	    public void setAsText(String text) throws IllegalArgumentException {
	        if (!StringUtils.isEmpty(text)) {
	        	String[] strs = text.split(",");
	            setValue(new Coordinate(Double.valueOf(strs[0]), Double.valueOf(strs[1])));
	        }
	    }
	}
	
	public class LocalTimeEditor extends PropertiesEditor {
	    @Override
	    public void setAsText(String text) throws IllegalArgumentException {
	        if (!StringUtils.isEmpty(text)) {
	            setValue(LocalTime.parse(text));
	        }
	    }
	}
}
